package study.activiti.ssh.web.action;


import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
import java.util.Map;

import javax.servlet.ServletOutputStream;

import org.activiti.engine.repository.Deployment;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.task.Comment;
import org.activiti.engine.task.Task;
import org.apache.commons.io.FileUtils;
import org.apache.struts2.ServletActionContext;

import study.activiti.ssh.domain.LeaveBill;
import study.activiti.ssh.service.ILeaveBillService;
import study.activiti.ssh.service.IWorkflowService;
import study.activiti.ssh.utils.SessionContext;
import study.activiti.ssh.utils.ValueContext;
import study.activiti.ssh.web.form.WorkflowBean;

import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionSupport;
import com.opensymphony.xwork2.ModelDriven;

@SuppressWarnings("serial")
public class WorkflowAction extends ActionSupport implements ModelDriven<WorkflowBean> {

	private WorkflowBean workflowBean = new WorkflowBean();
	
	public WorkflowBean getModel() {
		return workflowBean;
	}
	
	private IWorkflowService workflowService;
	
	private ILeaveBillService leaveBillService;

	public void setLeaveBillService(ILeaveBillService leaveBillService) {
		this.leaveBillService = leaveBillService;
	}

	public void setWorkflowService(IWorkflowService workflowService) {
		this.workflowService = workflowService;
	}

	/**  
	* @Name: deployHome（方法的名称）
	* @Description: 部署管理首页显示（方法的描述）
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-16 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	public String deployHome(){
		//1、查询部署对象信息，对应表（act_re_deployment）
		List<Deployment> depList = workflowService.findDeploymentList() ;
		//2、查询流程定义信息，对应表（act_re_procdef）
		List<ProcessDefinition> pdList = workflowService.findProcessDefinitionList() ;
		//将查询结果放入到request请求域范围中
		//ServletActionContext.getRequest().setAttribute("depList", depList) ;
		//ServletActionContext.getRequest().setAttribute("pdList", pdList) ;
		//将查询结果放入到值栈上下文中
		ValueContext.putValueContext("depList", depList) ;
		ValueContext.putValueContext("pdList", pdList) ;
		return "deployHome";
	}
	
	/**  
	* @Name: newdeploy（方法的名称）
	* @Description: 发布流程（zip格式）（方法的描述）
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-16 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	public String newdeploy(){
		//获取页面传递的值
		//获取页面上传递的流程资源文件，格式是File类型
		File file = workflowBean.getFile() ;
		//获取文件名
		String filename = workflowBean.getFilename() ;
		//部署流程定义（zip格式）
		workflowService.saveNewdeploy(file, filename) ;
		return "list";
	}
	
	/**  
	* @Name: delDeployment（方法的名称）
	* @Description: 删除部署对象，级联删除流程资源定义信息（方法的描述）
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-16 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	public String delDeployment(){
		//获取部署对象id
		String deploymentId = workflowBean.getDeploymentId() ;
		//删除部署对象，级联删除流程资源定义信息
		workflowService.deleteDeployment(deploymentId) ;
		return "list";
	}
	
	/**  
	* @Name: viewImage（方法的名称）
	* @Description: 查看流程图（方法的描述）
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-16 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	* @throws IOException
	*/
	public String viewImage() throws IOException{
		//获取部署对象id
		String deploymentId = workflowBean.getDeploymentId() ;
		//获取流程图片名称
		String imageName = workflowBean.getImageName() ;
		//获取资源文件表中的流程资源图片输入流
		InputStream in = workflowService.findImageInputStream(deploymentId, imageName) ;
		//显示流程图片
		//方式一：使用输出流将图片写到页面上
		//从response对象获取输出流
		OutputStream out = ServletActionContext.getResponse().getOutputStream() ;
		//将输入流中的数据读取出来，写到输出流中
		for(int b=-1; (b=in.read())!=-1;) {
			out.write(b) ;
		}
		out.close() ;
		in.close() ;
		//方式二：将图片写到磁盘，页面中使用<img>标签获取图片资源 
		//FileUtils.copyInputStreamToFile(in, new File("D:/" + imageName)) ;
		return null;
	}
	
	/**  
	* @Name: startProcess（方法的名称）
	* @Description: 启动流程实例（方法的描述）
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-16 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	public String startProcess(){
		workflowService.saveStartProcess(workflowBean) ;
		return "listTask";
	}
	
	/**  
	* @Name: listTask（方法的名称）
	* @Description: 任务管理首页显示（方法的描述）
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-16 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	public String listTask(){
		//查询正在执行的个人任务列表
		//从session中获取当前登录用户名
		String loginName = SessionContext.get().getName() ;
		List<Task> taskList = workflowService.findMyPersonalTask(loginName) ;
		//将查询结果放入到值栈上下文中
		ValueContext.putValueContext("taskList", taskList) ;
		return "task";
	}
	
	/**  
	* @Name: viewTaskForm（方法的名称）
	* @Description: 打开任务办理表单（方法的描述）
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-16 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	public String viewTaskForm(){
		//获取任务id
		String taskId = workflowBean.getTaskId() ;
		//获取任务节点的action请求链接
		String url = workflowService.findTaskFormByTaskId(taskId) ;
		//将任务节点的url请求链接放入到值栈上下文中
		url += "?taskId=" + taskId ;
		ValueContext.putValueContext("url", url) ;
		return "viewTaskForm";
	}
	
	/**  
	* @Name: audit（方法的名称）
	* @Description: 准备表单数据（方法的描述）
	* 1、使用任务id，获取请假单信息
	* 步骤：
	* 	1、使用任务id，查询正在执行的任务表，获取流程实例id
	* 	2、使用流程实例id，查询执行对象表，获取BUSSNESS_KEY的值，该值是工作流程与业务的关联字段，存放内容为【流程定义的key（等于请假业务类名）.业务表主键（请假业务表主键id）】
	* 	3、从BUSSNESS_KEY字段中获取请假单主键id
	* 	4、使用请假单主键id，查询请假单信息
	* 2、使用任务id，查询ProcessDefinitionEntity对象（对应流程定义文件，例LeaveBill.bpmn文件），获取当前任务完成之后的连线名称
	* 3、使用任务id，查询所有历史审核人的审核信息，帮助当前人完成审核，返回List<Comment>
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-17 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	public String audit(){
		//1、使用任务id获取请假单信息
		//获取任务id
		String taskId = workflowBean.getTaskId() ;
		//使用任务id，获取请假单信息
		LeaveBill leaveBill = workflowService.findLeaveBillByTaskId(taskId) ;
		//将请假单信息放入到栈顶
		ValueContext.putValueStack(leaveBill) ;
		//2、使用任务id查询ProcessDefinitionEntity对象，获取当前任务完成之后的连线名称
		List<String> outcomeList = workflowService.findOutcomeListByTaskId(taskId) ;
		ValueContext.putValueContext("outcomeList", outcomeList) ;
		//3、使用任务id，查询所有历史审核人的审核信息，帮助当前人完成审核，返回List<Comment>
		List<Comment> commentList = workflowService.findCommentByTaskId(taskId) ;
		ValueContext.putValueContext("commentList", commentList) ;
		return "taskForm";
	}
	
	/**  
	* @Name: submitTask（方法的名称）
	* @Description: 提交任务（方法的描述）
	* 操作：使用任务id，完成当前人的个人任务
	* 完成任务之前：
	* 	如果连线的名称是“默认提交”，即没有连线分支，直接提交
	* 	如果连线名称不是“默认提交”，设置流程变量，按照连线的名称，控制流程的走向
	* 		流程变量的名称：outcome
	* 		流程变量的值：连线的名称
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-17 （创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	public String submitTask(){
		workflowService.saveSubmitTask(workflowBean) ;
		return "listTask";
	}
	
	/**  
	 * @Name: viewCurrentImage（方法的名称）
	* @Description: 查看当前流程图（查看当前活动节点，并使用红色的框标注）（方法的描述）
	* 操作：
	* 	1、查看流程图
	* 		1、获取任务id，获取任务对象，使用任务对象获取流程定义id，查询流程定义对象
	* 		2、将部署对象id和流程资源图片名称放入到值栈上下文中
	*	2、查看当前活动
	*		获取当前活动对应的坐标x,y,width,height，将坐标放入到Map<String, Object>中
	*		key：为坐标x,y,width,height
	*		value：为坐标对应的值
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-18（创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	public String viewCurrentImage() {
		//获取任务id
		String taskId = workflowBean.getTaskId() ;
		//根据任务id，查询正在执行的任务表，获取流程定义对象
		ProcessDefinition pd = workflowService.findProcessDefinitionByTaskId(taskId) ;
		//使用流程定义对象，获取部署id和图片资源名称
		String deploymentId = pd.getDeploymentId() ;
		String imageName = pd.getDiagramResourceName() ;
		//将部署id和图片资源名称放入到值栈上下文中
		ValueContext.putValueContext("deploymentId", deploymentId) ;
		ValueContext.putValueContext("imageName", imageName) ;
		//获取当前活动对应的坐标x,y,width,height，将坐标放入到Map<String, Object>中
		Map<String, Object> map = workflowService.findCoordinatesByTaskId(taskId) ;
		//将Map结合放入到值栈上下文中
		ValueContext.putValueContext("acs", map) ;
		return "image";
	}
	
	/**  
	* @Name: viewHisComment（方法的名称）
	* @Description: 查看历史的批注信息（方法的描述）
	* 1、使用申请单id，查询请假单信息
	* 2、使用请假单id，查询请假申请的历史批注信息（重点：使用业务字段查询流程数据信息）
	* @Author: 李超（作者）
	* @Version: V1.00 （版本号）
	* @Create Date: 2016-12-17（创建日期）
	* @Parameters: 无（方法的入参，如果没有，填写为“无”）
	* @Return: 无（返回值，如果没有，填写为“无”）
	*/
	public String viewHisComment(){
		//1、使用申请单id，查询请假单信息
		//获取请假申请单id
		Long id = workflowBean.getId() ;
		//使用请假申请单id查询请假单信息
		LeaveBill leaveBill = leaveBillService.findLeaveBillById(id) ;
		//将查询结果放入到栈顶，支持表单回显
		ValueContext.putValueStack(leaveBill) ;
		//2、使用请假单id，查询请假申请的历史批注信息
		List<Comment> commentList = workflowService.findCommentByBusinessId(id) ;
		ValueContext.putValueContext("commentList", commentList) ;
		return "viewHisComment";
	}
}
